<?php

namespace App\Model;


use App\Services\AdapayService;
use Hyperf\Utils\Arr;
use Util\Common;

/**
 * App\Bill
 *
 * @property int $id
 * @property int $account_id 账户ID
 * @property string $account_type 账户类型
 * @property string $number 订单号
 * @property string $title 账单
 * @property int $fee 金额
 * @property string $type 类型
 * @property string $payment_type 支付方式
 * @property int $balance 账单发生后余额
 * @property int $refunded_fee 退款金额
 * @property array|null $extra 其他信息
 * @property int|null $target_id 账单指向的目标id 如订单id
 */
class Bill extends Model
{
    //
    public bool $timestamps = true;
    protected ?string $table = 'bills';

    const PAYMENT_TYPE_WE_CHAT_PAY = 'wx_lite';
    const PAYMENT_TYPE_ALI_PAY = 'alipay_lite';
    const PAYMENT_TYPE_SYSTEM = 'system';
    const PAYMENT_TYPE_BALANCE = 'balance';
    const PAYMENT_TYPE_IC_CARD = 'ic_card';

    const PAYMENT_TYPE_MAP = [
        self::PAYMENT_TYPE_WE_CHAT_PAY => '微信',
        self::PAYMENT_TYPE_ALI_PAY => '支付宝',
        self::PAYMENT_TYPE_SYSTEM => '系统划账',
        self::PAYMENT_TYPE_BALANCE => '余额',
        self::PAYMENT_TYPE_IC_CARD => 'IC卡',
    ];
    const TYPE_CHARGE_BALANCE = 'charge_balance';
    const TYPE_CHARGE_BALANCE_GIVE = 'charge_balance_give';
    const TYPE_ORDER_PAY = 'order_pay';
    const TYPE_USER_WITHDRAW = 'user_withdraw';
    const TYPE_REFUND = 'refund';
    const TYPE_DEVICE_JOIN_DEPOSIT = 'device_join_deposit';
    const TYPE_DEVICE_JOIN_DEPOSIT_REFUND = 'device_join_deposit_refund';

    const TYPE_DISTRIBUTOR_ORDER_PROFIT = 'distributor_order_profit';
    const TYPE_DISTRIBUTOR_DIRECT_ORDER_PROFIT = 'distributor_direct_order_profit';
    const TYPE_DISTRIBUTOR_WITHDRAW = 'distributor_withdraw';
    const TYPE_DISTRIBUTOR_WITHDRAW_RETURN = 'distributor_withdraw_return';
    const TYPE_DISTRIBUTOR_DEVICE_RENEW = 'distributor_device_renew';

    const TYPE_CHARGE_REFUND = 'charge_refund';

    const TYPE_PLATFORM_PROFIT = 'platform_profit';

    const TYPE_MAP = [
        self::TYPE_CHARGE_BALANCE => '余额充值',
        self::TYPE_CHARGE_BALANCE_GIVE => '余额送',

        self::TYPE_ORDER_PAY => '订单支付',

        self::TYPE_USER_WITHDRAW => '提现',
        self::TYPE_REFUND => '退款',
        self::TYPE_DEVICE_JOIN_DEPOSIT => '加盟设备押金',
        self::TYPE_DEVICE_JOIN_DEPOSIT_REFUND => '加盟设备押金退回',

        self::TYPE_DISTRIBUTOR_ORDER_PROFIT => '分销订单收益',
        self::TYPE_DISTRIBUTOR_DIRECT_ORDER_PROFIT => '直营订单收益',
        self::TYPE_DISTRIBUTOR_WITHDRAW => '分销提现',
        self::TYPE_DISTRIBUTOR_WITHDRAW_RETURN => '分销提现退回',
        self::TYPE_DISTRIBUTOR_DEVICE_RENEW => '分销设备续费',

        self::TYPE_PLATFORM_PROFIT => '平台收益',

        self::TYPE_CHARGE_REFUND => '取消充值退款',
    ];

    const ACCOUNT_TYPE_MAP = [
        User::class => '用户',
        Distributors::class => '分销商',
    ];

    protected array $casts = [
        'extra' => 'json'
    ];

    protected array $fillable = [
        'fee', 'type', 'payment_type', 'description', 'extra'
    ];

    public function account()
    {
        return $this->morphTo();
    }


    public function getPaymentTypeDes()
    {
        return Arr::get(self::PAYMENT_TYPE_MAP, $this->payment_type);
    }
    public function getAccountDes()
    {
        $accountTypeDes = $this->account_type ? Arr::get(Bill::ACCOUNT_TYPE_MAP, $this->account_type) : '平台';
        $accountArr = $this->account->toArray();
        return '[' . $accountTypeDes . '] ' . Arr::get($accountArr, 'name', Arr::get($accountArr, 'nickname', Arr::get($accountArr, 'sn')));
    }

    /**
     * @param $account Distributor|User|Model 账户
     * @param $fee float 变动金额
     * @param $type string 账单类型
     * @param $paymentType string|null 支付类型
     * @param int $targetId 关联目标id 如订单id
     * @param array $extra 扩展字段
     * @param $description string|null 简介
     * @return Bill
     * 记账
     */
    public static function record($account, $fee, $type, $paymentType = Bill::PAYMENT_TYPE_SYSTEM, $targetId = null, $extra = [], $description = null)
    {
        //记账
        $bill = new static();
        $bill->fee = $fee;
        $bill->type = $type;
        $bill->description = $description;
        $bill->extra = $extra;
        $bill->payment_type = $paymentType;
        $bill->target_id = $targetId;

        //平台收益没有账号
        if($account) {
            //关联账户
            $bill->balance = $account->balance + $account->frozen_balance;
            $bill->account()->associate($account);
        }
        //没有编号 或者编号已经存在 就重新生成一个编号 再检验
        while (is_null($bill->number) || Bill::whereNumber($bill->number)->exists()) {
            $bill->number = rand_number(rand(1, 99999), 18);
        }
        $bill->save();
        return $bill;
    }


    /**
     * @param Order|Model $targetObject
     * @param string $reason 退款原因
     */
    public function refund($targetObject, $reason)
    {
        $absFee = abs($this->fee);

        $account = $this->account;

        switch ($this->payment_type)
        {
            //余额支付退回
            case self::PAYMENT_TYPE_BALANCE:
                $account->increment('balance', $absFee);
                //记账
                Bill::record(
                    $account,
                    $absFee,
                    Bill::TYPE_REFUND,
                    Bill::PAYMENT_TYPE_SYSTEM,
                    $targetObject->id
                );
                break;

            //支付宝支付退回
            case self::PAYMENT_TYPE_ALI_PAY:
            //微信支付退回
            case self::PAYMENT_TYPE_WE_CHAT_PAY:
                $refoundParams = array(
                    "payment_id"=> $targetObject->payment_id,
                    # 退款订单号
                    "refund_order_no"=> $targetObject->number,
                    # 退款金额
                    "refund_amt"=> $targetObject-> fee,
                    "notify_url" =>Common::MAIN_HOST.'/user/order/refund'
                );
                $adapayService = new AdapayService();
                $result = $adapayService->refundPayment($refoundParams);
                var_dump($result);
                break;

//            //平台收益记一笔退款
//            case self::PAYMENT_TYPE_SYSTEM:
//
//                switch ($this->type) {
//                    //分销收益退回
//                    case self::TYPE_DISTRIBUTOR_DIRECT_ORDER_PROFIT:
//                    case self::TYPE_DISTRIBUTOR_ORDER_PROFIT:
//                        $account->decrement('balance', $absFee);
//                        if($account instanceof Distributor) {
//                            $account->decrement('total_profit', $absFee);
//                        }
//
//                        //记账
//                        Bill::record(
//                            $account,
//                            - $absFee,
//                            Bill::TYPE_REFUND,
//                            Bill::PAYMENT_TYPE_SYSTEM,
//                            $targetObject->id
//                        );
//                        break;
//
//                    case self::TYPE_PLATFORM_PROFIT:
//                        //记账
//                        Bill::record(
//                            $account,
//                            - $absFee,
//                            Bill::TYPE_REFUND,
//                            Bill::PAYMENT_TYPE_SYSTEM,
//                            $targetObject->id
//                        );
//                        break;
//
//                    default:
//                        abort(500, 'refund type invalid ' . $this->type);
//                }
//                break;
//
            default:
                abort(500, 'refund payment type invalid ' . $this->payment_type);
        }

    }

}
